package otw.dao.ibatis.base;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.Assert;

import otw.utils.generics.GenericsUtils;
import otw.utils.pagination.Page;

import com.ibatis.sqlmap.client.SqlMapClient;

/**
 * <p>
 * 继承自 IbatisGenericsDao 实现类 类级别 的 泛型，可以作为所有 dao 类的 超类
 * </p>
 * <p>
 * insert 插入1条记录
 * </p>
 * <p>
 * getById 根据主键获得1条记录<br>
 * getByObject 根据对象获得1条记录<br>
 * </p>
 * <p>
 * updateById 根据id更新1条记录<br>
 * updateByObject 根据 对象 更新1条记录<br>
 * </p>
 * <p>
 * deleteById 根据主键删除1条记录<br>
 * deleteByObject 根据1系列参数删除满足条件的记录<br>
 * </p>
 * <p>
 * getByMap 根据1系列参数获得满足条件的记录<br>
 * countByMap 根据1系列参数获得满足条件的记录总数<br>
 * </p>
 * <p>
 * getByPage 获得封装后的一页数据<br>
 * </p>
 * 
 * @author space
 * @date Jun 14, 2008 2:31:34 PM
 * @param <T>
 *            具体类 dao 类 中操作的 domain 类的类型
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class IbatisEntityDao<T> extends IbatisGenericsDao implements DaoBase<T> {
	/**
	 * 默认的构造函数； 子类构造时可以获得自己所指定的具体泛型的类型；
	 */
	public IbatisEntityDao() {
		this.entityClass = GenericsUtils.getSuperClassGenricType(this.getClass());
	}

	/**
	 * 初始化 SqlMapClientDaoSupport 中的 sqlMapClient 属性;自动被调用，相当于初始化；
	 * 
	 * @param sqlMapClient
	 */
	@Autowired
	public void initSqlMapClient(@Qualifier("sqlMapClient") SqlMapClient sqlMapClient) {
		super.setSqlMapClient(sqlMapClient);
	}

	/**
	 * 是泛型的具体类型，在子类中构造对象时 指定该值（通过构造函数）
	 */
	protected Class<T> entityClass;

	/**
	 * @return
	 */
	public Class<T> getEntityClass() {
		return this.entityClass;
	}

	/**
	 * 插入一条记录
	 * 
	 * @param t
	 * @return 新生成记录的 主键
	 */
	public Object insert(T t) {
		return super.insert(entityClass, t);
	}

	/**
	 * 获得一条记录，根据主键查询
	 * 
	 * @param id
	 * @return
	 */
	public T getById(Integer id) {
		return super.getById(entityClass, id);
	}

	/**
	 * 获得一条记录，根据对象查询
	 * 
	 * @param t
	 * @return
	 */
	public T getByObject(T t) {
		return super.getByObject(entityClass, t);
	}

	/**
	 * 更新一条记录，根据主键
	 * 
	 * @param id
	 */
	public int updateById(Serializable id) {
		return super.updateById(entityClass, id);
	}

	/**
	 * 更新一条记录，根据对象
	 * 
	 * @param t
	 */
	public int updateByObject(T t) {
		return super.updateByObject(entityClass, t);
	}

	/**
	 * 删除一条记录，根据主键
	 * 
	 * @param id
	 */
	public int deleteById(Serializable id) {
		return super.deleteById(entityClass, id);
	}

	/**
	 * 删除一条记录，根据对象
	 * 
	 * @param t
	 */
	public int deleteByObject(T t) {
		return super.deleteByObject(entityClass, t);
	}

	/**
	 * 根据一系列参数，查询
	 * 
	 * @param param
	 * @return
	 */
	public List<T> getByMap(Map param) {
		return super.getByMap(entityClass, param);
	}

	/**
	 * 根据一系列参数，查询满足条件的总数
	 * 
	 * @param param
	 * @return
	 */
	public Integer countByMap(Map param) {
		return super.countByMap(entityClass, param);
	}

	/**
	 * 根据一系列参数，求得封装后的一页数据；
	 * 
	 * @param param
	 * @return
	 */
	public Page<T> getByPage(Map param) {
		Assert.notNull(param, "param must not be null!");

		Integer size = (Integer) param.get(Page.SIZE_PARAM);
		Integer pageNum = (Integer) param.get(Page.PAGE_NUM_PARAM);

		if (pageNum == null || pageNum < 1) {
			pageNum = 1;
		}
		if (size == null || size < 1 || size > Page.SIZE_MAX_LIMIT) {
			size = Page.SIZE_DEFAULT;
		}

		// 计算总数
		Integer totalCount = this.countByMap(param);
		// 计算 start
		Integer start = (Integer) Page.figureStart(pageNum, size, totalCount);
		// 获得一页数据
		param.put(Page.START_PARAM, start);
		param.put(Page.SIZE_PARAM, size);
		param.put(Page.PAGE_NUM_PARAM, pageNum);
		List<T> data = this.getByMap(param);

		Page<T> page = new Page<T>();
		page.setSize(size);
		page.setTotal(totalCount);
		page.setStart(start);
		Integer totalPn = Page.figureMaxPageNum(size, totalCount);
		page.setTotalPageNum(totalPn);
		// 纠正了 pageNum
		page.setPageNum(Page.figurePageNum(pageNum, totalPn));
		page.setData(data);
		// 查询后，Page 的 paramMap 中不保存 size,start，仅保存查询参数
		param.remove(Page.SIZE_PARAM);
		param.remove(Page.START_PARAM);
		param.remove(Page.PAGE_NUM_PARAM);
		page.setParamMap(param);
		return page;
	}
}